package com.yuelan.codelib.download;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.text.TextUtils;
import android.view.WindowManager;
import android.widget.Toast;

import com.yuelan.codelib.utils.HttpConnent;
import com.yuelan.codelib.utils.ImageDownloader;
import com.yuelan.codelib.utils.ImageDownloader.OnImageDownload;
import com.yuelan.codelib.utils.encryption.MD5Encoder;
import com.yuelan.codelib.utils.LOG;
import com.yuelan.codelib.utils.MathUtil;
import com.yuelan.codelib.utils.SDCardUtil;
import com.yuelan.codelib.utils.TextUtil;

public class TpUtil {
	public final static long APPSIZE_MAX = 1024 * 1024 * 100;

	public static String getACTION_DOWNLOAD(Context c) {
		return c.getPackageName() + "BroadCast_download_app";
	}

	/**
	 * @param c
	 * @param gameId
	 * @param name
	 * @param url
	 * @param type
	 *            下载类型1 有通知栏 2没有通知栏
	 * @param apkDir
	 * @param multiThreading
	 *            是否开启队列
	 * @param appDummySize
	 * @param appIconUrl
	 * @param ad_Id
	 *            广告位ID
	 * @param packageName
	 * @param popupType
	 *            下载完成后类型
	 * @param popupText
	 *            安装后弹出的广告语
	 * @param apkpathtype
	 *            apk的路径类型 我们的文件夹还是根目录
	 */
	public static void goToDownloadApk(final Context c, final String appId,
			final String name, String downloadurl, String type, String apkDir,
			String appDummySize, String appIconUrl, int adid,
			String packageName, String popupType, String popupText, int pageid,
			long crc32, String dlCallBackUrl) {
		// LOG.v("goToDownloadApk ..."+);
		// LOG.v("goToDownloadApk crc32 = " + crc32);
		try {
			double a = Double.valueOf(appDummySize);
			if (a > 35) {
				a = 35;
			}
			long b = (long) (a * 1024 * 1024 * 3);
			if (!SDCardUtil.canUserSDCard(b)) {
				apkDir = c.getFilesDir().getAbsolutePath() + "/";
				LOG.v(apkDir);
			}
			if (a <= 0) {
				appDummySize = "10";
			}
		} catch (Exception e) {
			appDummySize = "10";
		}
		// LOG.v("appDummySize = " + appDummySize + "M");
		if (TextUtil.notNull(downloadurl) && downloadurl.startsWith("http")) {
			downloadurl = downloadurl.trim();
		} else {
			Toast.makeText(c, "Download URL exception!", Toast.LENGTH_SHORT)
					.show();
			return;
		}
		TpDB db = new TpDB(c);
		String sql_ = "select * from download_info where gameid = ? and packagename = ? ";
		Cursor cursor = db.query(sql_, new String[] { appId, packageName });
		int num = cursor.getCount();
		if (num == 0) {
			LOG.v("No data in database.");
			String sql = "insert into download_info(name,gameid,type,url,state,filepath,iconurl,adid,packagename,popuptype,popupText,appsize,pageid,crc32,dlcallbackurl) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
			db.execSQL(sql, new Object[] { name, appId, type, downloadurl, "0",
					apkDir, appIconUrl, adid, packageName, popupType,
					popupText, appDummySize, pageid, crc32, dlCallBackUrl });
			prepareDownload(c, type, appId, name, packageName, appDummySize,
					appIconUrl, false);
		} else {
			LOG.v("Database got datas.");
			cursor.moveToNext();
			String filename = name + "."
					+ cursor.getString(TpDB.Index_FileType);
			File file = new File(apkDir + filename);
			if (file.exists()) {
				LOG.v("File exists.");
				String state = cursor.getString(TpDB.Index_State);
				if (state.equals("1")) {
					LOG.v("Database data download success.");
					long TotleFileSize = -1;
					try {
						String TotleFileSize_STR = cursor
								.getString(TpDB.Index_DownFileSize);
						if (TextUtil.notNull(TotleFileSize_STR)) {
							TotleFileSize = Long.valueOf(TotleFileSize_STR);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
					if (checkValidity(file, TotleFileSize, crc32)) {
						// crc32
						String finalFilePath = apkDir + filename;
						String cmd = "chmod 777 " + finalFilePath;
						try {
							Runtime.getRuntime().exec(cmd);
						} catch (IOException e) {
							e.printStackTrace();
						}
						final Intent intent = new Intent(Intent.ACTION_VIEW);
						File apkFile = new File(finalFilePath);
						intent.setDataAndType(Uri.fromFile(apkFile),
								"application/vnd.android.package-archive");
						if (popupType.equals("3")) {
							Dialog alertDialog = new AlertDialog.Builder(c)
									.setCancelable(false)
									.setPositiveButton("确定",
											new OnClickListener() {
												@Override
												public void onClick(
														DialogInterface arg0,
														int arg1) {
													intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
													c.startActivity(intent);
												}
											}).setMessage(popupText).create();
							alertDialog
									.getWindow()
									.setType(
											WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
							alertDialog.show();
						} else if (popupType.equals("2")) {
							intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
							c.startActivity(intent);
							Intent it = new Intent(
									Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
							c.sendBroadcast(it);
						} else {

						}
					} else {
						LOG.v("Unanimous local file size with database ,will delete and re-download.");
						String sql = "update download_info set state = ?,downloadfilesize = ? where gameid = ? and packagename = ? ";
						db.execSQL(sql, new Object[] { 0 + "", 0 + "",
								appId + "", packageName });
						prepareDownload(c, type, appId, name, packageName,
								appDummySize, appIconUrl, false);
					}
				} else {
					LOG.v("Database record download uncomplete, retrying.");
					String sql = "update download_info set state = ? where gameid = ? and packagename = ? ";
					db.execSQL(sql, new Object[] { 0 + "", appId, packageName });
					prepareDownload(c, type, appId, name, packageName,
							appDummySize, appIconUrl, true);
				}
			} else {
				LOG.v("File doesn't exist.");
				String sql = "update download_info set state = ?,downloadfilesize = ? where gameid = ? and packagename = ? ";
				db.execSQL(sql, new Object[] { 0 + "", 0 + "", appId + "",
						packageName });
				prepareDownload(c, type, appId, name, packageName,
						appDummySize, appIconUrl, false);
			}
		}
		cursor.close();
		db.close();
	}

	private static boolean checkValidity(File file, long size, long crc32) {
		if (size != file.length())
			return false;
		LOG.v("checkValidity crc32 = " + crc32);
		if (crc32 != 0 && MD5Encoder.sysstatisCrcCalcFile(file) != crc32)
			return false;
		return true;
	}

	private static void prepareDownload(final Context context, String type,
			final String appId, final String name, final String packagename,
			final String appSize, String appIconUrl, final boolean isGoon) {
		final TpNfView dnv = new TpNfView(context);
		if (type.equals("1")) {
			ImageDownloader.imageDownload(appIconUrl, context,
					new OnImageDownload() {
						@Override
						public void onDownloadSucc(Bitmap imageDrawable) {
							if (isGoon) {
								TpDB db = new TpDB(context);
								final TpInfo downloadInfo = db
										.getDownloadInfoForId(appId,
												packagename);
								String downloadFileSize = downloadInfo
										.getDownloadFileSize();
								String totalFileSize = downloadInfo
										.getTotalFileSize();
								if (downloadInfo != null
										&& TextUtil.notNull(downloadFileSize)
										&& TextUtil.notNull(totalFileSize)) {
									final double finalPercent = (Double
											.parseDouble(downloadFileSize) / Double
											.parseDouble(totalFileSize)) * 100;
									final String appDummySize = downloadInfo
											.getAppDummySize();
									dnv.showDownloadView(
											name,
											0,
											imageDrawable,
											(MathUtil.roundDouble(
													finalPercent
															* 0.01
															* Double.parseDouble(appDummySize),
													2))
													+ "M/" + appDummySize + "M",
											(int) finalPercent, "等待下载", Integer
													.valueOf(appId), null,
											false);

								} else {

									dnv.showDownloadView(name, 0,
											imageDrawable, 0 + "M/" + appSize
													+ "M", 0, "等待下载",
											Integer.valueOf(appId), null, false);

								}
							} else {

								dnv.showDownloadView(name, 0, imageDrawable, 0
										+ "M/" + appSize + "M", 0, "等待下载",
										Integer.valueOf(appId), null, false);

							}
						}
					}, 200);
		}
		Intent intent = new Intent(context, TpService.class);
		intent.setAction(TpService.ACTION_DOWNLOAD_BASIC);
		context.startService(intent);
	}

	// private static void pauseDownload(Context c, DownloadDB db, String
	// gameId) {
	// String sql = "update download_info set state = ? where gameid = ?";
	// db.execSQL(sql, new Object[] { -1 + "", gameId + "" });
	// }
	/**
	 * @param url
	 * @param filePath
	 * @param type
	 * @param c
	 * @param id
	 * @param db
	 * @param appName
	 * @param appIconUrl
	 * @param AD_ID
	 * @param packageName
	 * @param popupType
	 * @param popupText
	 * @param appDummySize
	 * @return
	 */
	public static void doHttpDownloadApk(String downloadurl,
			final String filePathIn, final int type, final Context c,
			final String id, final TpDB db, final String appName,
			final String appIconUrl, final int adid, final String packageName,
			final String popupType, final String popupText,
			final String appDummySize, final int pageid, final long crc32,
			final String dlcallbackurl, final int times) {
		boolean isRetry = false;
		LOG.v("doHttpDownloadApk times = " + times + " ...");
		HttpFileInfo info = getHttpFileInfo(downloadurl);
		LOG.v("doHttpDownloadApk getName = " + info.getName() + ", getSize = "
				+ info.getSize() + ", getFormat = " + info.getFormat());
		String contentType = info.getFormat();
		String filePath = filePathIn;
		if (contentType != null) {
			String sql = "update download_info set filetype = ? where gameId = ?  and packagename = ? ";
			db.execSQL(sql, new Object[] { contentType, id, packageName });
			filePath = filePath + contentType;
		}
		LOG.v(filePath + "filePath");
		File localFile = new File(filePath);
		long localSize = localFile.length();
		LOG.v("localSize = " + localSize);
		if (TextUtils.isEmpty(downloadurl)) {
			return;
		}
		InputStream is = null;
		RandomAccessFile fos = null;
		long downloadfilesize = 0;
		long realSize = 0;
		// String failInfo = null;
		try {
			realSize = Long.valueOf(info.getSize());
			LOG.v("realSize = " + realSize);
			String sql = "update download_info set totalFileSize = ? where gameId = ? and packagename = ? ";
			db.execSQL(sql, new Object[] { realSize + "", id, packageName });
			if (realSize < localSize && realSize != -1) {
				localFile.delete();
				localSize = 0;
			}
			if (checkValidity(localFile, realSize, crc32)) {
				String in = id + "#_#" + "YES" + "#_#"
						+ (downloadfilesize + localSize) + "#_#" + realSize
						+ "#_#" + appName + "#_#" + appIconUrl + "#_#" + adid
						+ "#_#" + packageName + "#_#" + popupType + "#_#"
						+ popupText + "#_#" + filePath + "#_#" + appDummySize
						+ "#_#" + type + "#_#" + pageid + "#_#" + dlcallbackurl;
				Intent intent = new Intent(getACTION_DOWNLOAD(c));
				intent.putExtra("info", in);
				c.sendBroadcast(intent);
				return;
			}
			DefaultHttpClient clientReally = HttpConnent.getHttpClient();
			HttpGet requestReally = new HttpGet(downloadurl);
			// 设置下载的数据位置XX字节到XX字节
			if (localSize > 0) {
				Header header_size = new BasicHeader("Range", "bytes="
						+ localSize + "-");
				LOG.v("设置" + localSize + "-" + realSize);
				requestReally.addHeader(header_size);
			}
			HttpResponse responseReally = clientReally.execute(requestReally);
			HttpEntity httpEntityReally = responseReally.getEntity();
			if (realSize > 0 || realSize == -1) {
				is = httpEntityReally.getContent();
				if (is == null) {
					throw new RuntimeException("stream is null");
				} else {
					if (realSize == -1) {
						realSize = APPSIZE_MAX;
						LOG.v("available" + realSize);
					}
				}
				fos = new RandomAccessFile(localFile, "rw");
				fos.seek(localSize);
				byte buf[] = new byte[1024 * 8];
				long lasttime = System.currentTimeMillis();
				LOG.v("read http ...");
				do {
					int numread = is.read(buf);
					if (numread <= 0) {
						break;
					}
					fos.write(buf, 0, numread);
					downloadfilesize += numread;
					if (type == 1) {
						long nowtime = System.currentTimeMillis();
						if (nowtime - lasttime > 1000) {
							String in = id + "#_#" + "ING" + "#_#"
									+ (downloadfilesize + localSize) + "#_#"
									+ realSize + "#_#" + appName + "#_#"
									+ appIconUrl + "#_#" + adid + "#_#"
									+ packageName + "#_#" + popupType + "#_#"
									+ popupText + "#_#" + filePath + "#_#"
									+ appDummySize + "#_#" + type + "#_#"
									+ pageid + "#_#" + dlcallbackurl;
							Intent intent = new Intent(getACTION_DOWNLOAD(c));
							intent.putExtra("info", in);
							c.sendBroadcast(intent);
							lasttime = nowtime;
						}
					}
					// 暂停下载
				} while (true);
				LOG.v("read http over");
				is.close();
				// 下载成功
				if (checkValidity(new File(filePath), downloadfilesize, crc32)) {
					String in = id + "#_#" + "YES" + "#_#" + downloadfilesize
							+ "#_#" + downloadfilesize + "#_#" + appName
							+ "#_#" + appIconUrl + "#_#" + adid + "#_#"
							+ packageName + "#_#" + popupType + "#_#"
							+ popupText + "#_#" + filePath + "#_#"
							+ appDummySize + "#_#" + type + "#_#" + pageid
							+ "#_#" + dlcallbackurl;
					Intent intent = new Intent(getACTION_DOWNLOAD(c));
					intent.putExtra("info", in);
					c.sendBroadcast(intent);
				} else {
					if (times < 3) {
						isRetry = true;
					} else {
						String failInfo = id + "#_#" + "NO" + "#_#"
								+ (downloadfilesize + localSize) + "#_#"
								+ realSize + "#_#" + appName + "#_#"
								+ appIconUrl + "#_#" + adid + "#_#"
								+ packageName + popupType + "#_#" + popupText
								+ "#_#" + filePath + "#_#" + appDummySize
								+ "#_#" + type;
						Intent intent = new Intent(getACTION_DOWNLOAD(c));
						intent.putExtra("info", failInfo);
						c.sendBroadcast(intent);
					}
				}
			}
			// }
		} catch (Exception e) {
			LOG.v("download Exception");
			e.printStackTrace();
			String failInfo = null;
			if (TextUtil.notNull(info.getSize()) && downloadfilesize != 0) {
				long savesize = downloadfilesize + localSize;
				failInfo = id + "#_#" + "NO" + "#_#" + savesize + "#_#"
						+ realSize + "#_#" + appName + "#_#" + appIconUrl
						+ "#_#" + adid + "#_#" + packageName;
				String sql = "update download_info set downloadfilesize = ? where gameid = ? and packagename = ? ";
				db.execSQL(sql, new Object[] { savesize + "", id + "",
						packageName });

			} else {
				TpInfo downloadInfo = db.getDownloadInfoForId(id, packageName);
				if (downloadInfo != null
						&& TextUtil.notNull(downloadInfo.getDownloadFileSize())
						&& TextUtil.notNull(downloadInfo.getTotalFileSize())) {
					failInfo = id + "#_#" + "NO" + "#_#"
							+ downloadInfo.getDownloadFileSize() + "#_#"
							+ downloadInfo.getTotalFileSize() + "#_#" + appName
							+ "#_#" + appIconUrl + "#_#" + adid + "#_#"
							+ packageName;
				} else {
					failInfo = id + "#_#" + "NO" + "#_#" + 0 + "#_#" + 100
							+ "#_#" + appName + "#_#" + appIconUrl + "#_#"
							+ adid + "#_#" + packageName;
				}
			}
			if (times < 3) {
				isRetry = true;
			} else {
				LOG.v(failInfo);
				Intent intent = new Intent(getACTION_DOWNLOAD(c));
				intent.putExtra("info", failInfo);
				c.sendBroadcast(intent);
			}
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				is = null;
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				fos = null;
			}
		}
		if (isRetry) {
			try {
				Thread.sleep(3000);
			} catch (Exception e) {
				// TODO: handle exception
			}
			doHttpDownloadApk(downloadurl, filePathIn, type, c, id, db,
					appName, appIconUrl, adid, packageName, popupType,
					popupText, appDummySize, pageid, crc32, dlcallbackurl,
					times + 1);
		}
	}

	public static HttpFileInfo getHttpFileInfo(String url) {
		HttpFileInfo info = new HttpFileInfo();
		String filename = "";
		URL myURL;
		HttpURLConnection conn = null;
		if (TextUtil.notNull(url) == false) {
			return null;
		}
		try {
			url = TextUtil.DmURLEncoder(url);
			myURL = new URL(url);
			conn = (HttpURLConnection) myURL.openConnection();
			conn.setRequestProperty("Accept-Encoding", "identity");
			conn.setConnectTimeout(5 * 1000);
			conn.setRequestMethod("GET");
			conn.setRequestProperty("Referer", url);
			conn.setRequestProperty("Charset", "UTF-8");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.connect();
			conn.getResponseCode();
			String acceptRange = conn.getHeaderField("Accept-Ranges");
			LOG.v(acceptRange + "-----------");
			URL absUrl = conn.getURL();
			int appSize = conn.getContentLength();
			LOG.v("appSize" + appSize);
			if (appSize > 20 * 1024) {
				info.setSize(conn.getContentLength() + "");
			} else {
				info.setSize("-1");
			}
			filename = absUrl.getFile();
			if (TextUtil.notNull(filename) == false) {
				filename = conn.getHeaderField("Content-Disposition");
			} else {
				if (filename.contains("?")) {
					int in = filename.indexOf("?");
					filename = filename.substring(0, in);
				}
			}
			info.setName(filename);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
		}
		String resType = null;
		if (TextUtil.notNull(filename) && filename.contains(".")) {
			int begin = filename.lastIndexOf(".");
			resType = filename.substring(begin + 1, filename.length())
					.replaceAll("\"", "");
		} else {
			resType = "apk";
		}
		info.setFormat(resType);
		return info;
	}

}
